
#include "audio_core.h"
#include "audio_vorbis.h"
#include "audio_synth.h"
#include "scripting.h"

using namespace WtfAudio;
using namespace WtfEngine;
using namespace boost::python;

/**
 * The WtfAudio Python module definition
 **/
BOOST_PYTHON_MODULE(WtfAudio) {
	class_<Data, Data::tRef, boost::noncopyable>("DataSource", no_init)
		.def("Reset", &Data::Reset)
		.add_property("format", &Data::getFormat)
		.add_property("bitRate", &Data::getBitRate)
	;
	implicitly_convertible<Data::tRef, WtfEngine::DataObject::tRef>();
	implicitly_convertible<Data::tRef, WtfEngine::DataObject::tCacheRef>();
	
	class_<tAudio, tAudio::tRef, bases<WtfEngine::IDataObject>, boost::noncopyable>("AudioSetting",
		init<const String&, AudioSample::tRefa>())
		.def_readwrite("value", &tAudio::Value)
	;
	implicitly_convertible<tAudio::tRef, WtfEngine::IDataObject::tCacheRef>();
	implicitly_convertible<tAudio::tRef, tAudio::tCacheRef>();

	class_<ScriptSettingWrapper<tAudio> >("Audio", init<String>())
		.add_property("value", &ScriptSettingWrapper<tAudio>::Get<AudioSample::tRef>, &ScriptSettingWrapper<tAudio>::operator =<AudioSample::tRef>)
		.def("Set", &ScriptSettingWrapper<tAudio>::Set<AudioSample::tRef>)
		.staticmethod("Set")
	;
	implicitly_convertible<ScriptSettingWrapper<tAudio>, tAudio::tRef>();


	class_<AudioSample, AudioSample::tRef, boost::noncopyable>("AudioSample",
		init<Data::tRefa>())
	;

	class_<BaseSound, BaseSound::tRef, boost::noncopyable>("BaseSound", init<tAudioRef&>())
		.def("Play", (void (BaseSound::*)(bool))&BaseSound::Play)
		.def("Stop", &BaseSound::Destroy)
	;

	class_<AudioStream, AudioStream::tRef, boost::noncopyable>("AudioStream", init<Data::tRefa>())
		.def("Play", (void (AudioStream::*)(bool))&AudioStream::Play)
		.def("Stop", &AudioStream::Stop)
		.add_property("isPlaying", &AudioStream::IsPlaying)
	;


	/**** Data Formats ****/

	class_<VorbisData, VorbisData::tRef, bases<Data>, boost::noncopyable>("VorbisData",
		init<const WtfEngine::StringPool::Entry&>())
	;
	implicitly_convertible<VorbisData::tRef, Data::tRef>();



	/**** Synthesizers ****/

	class_<Generator, Generator::tRef, bases<Data>, boost::noncopyable>("Generator", no_init)
	;
	implicitly_convertible<Generator::tRef, Data::tRef>();

	class_<IAmplitudeFunction, IAmplitudeFunction::tRef, boost::noncopyable>("IAmplitudeFunction", no_init)
	;
	class_<ISequencer, ISequencer::tRef, boost::noncopyable>("ISequencer", no_init)
	;


	class_<PcmOutput::tCreationOptions>("PcmOutputCreationOptions")
		.def_readwrite("format", &PcmOutput::tCreationOptions::DataFormat)
		.def_readwrite("bitRate", &PcmOutput::tCreationOptions::uBitRate)
	;
	class_<PcmOutput, PcmOutput::tRef, bases<Generator> >("PcmOutput",
		init<const WtfEngine::StringPool::Entry&, Data::tRefa, const PcmOutput::tCreationOptions&>())
	;
	implicitly_convertible<PcmOutput::tRef, Generator::tRef>();

	class_<WaveGenerator::tCreationOptions>("WaveGeneratorCreationOptions")
		.def_readwrite("ampFunction", &WaveGenerator::tCreationOptions::rAmplitudeFunction)
		.def_readwrite("sampleRate", &WaveGenerator::tCreationOptions::uOutputRate)
	;
	class_<WaveGenerator, WaveGenerator::tRef, bases<Generator> >("WaveGenerator",
		init<const WtfEngine::StringPool::Entry&, const WaveGenerator::tCreationOptions&>())
	;
	implicitly_convertible<WaveGenerator::tRef, Generator::tRef>();



	/**** Multiplexer ****/

	class_<Multiplexer::IType, Multiplexer::IType::tRef, boost::noncopyable>("IMultiplexerType", no_init)
	;
	class_<Multiplexer::tSourceList>("MultiplexerSourceList")
		.def(list_indexing_suite<Multiplexer::tSourceList>())
	;
	class_<Multiplexer, Multiplexer::tRef, bases<Generator> >("Multiplexer",
		init<const WtfEngine::StringPool::Entry&, Multiplexer::IType::tRefa>())
		.def("AddSource", &Multiplexer::AddSource)
		.def("RemoveSource", &Multiplexer::RemoveSource)
		.add_property("sources", make_function(&Multiplexer::getSources, return_value_policy<reference_existing_object>()))
	;
	implicitly_convertible<Multiplexer::tRef, Generator::tRef>();
	
	class_<Multiplexer::AdditiveType, Multiplexer::AdditiveType::tRef, bases<Multiplexer::IType> >
		("MultiplexerAdditiveType");
	implicitly_convertible<Multiplexer::AdditiveType::tRef, Multiplexer::IType::tRef>();


	class_<SineWaveFunction, SineWaveFunction::tRef>("SineWaveFunction",
		init<ISequencer::tRefa>())
	;
	implicitly_convertible<SineWaveFunction::tRef, IAmplitudeFunction::tRef>();

	class_<SquareWaveFunction, SquareWaveFunction::tRef>("SquareWaveFunction",
		init<ISequencer::tRefa>())
	;
	implicitly_convertible<SquareWaveFunction::tRef, IAmplitudeFunction::tRef>();


	class_<ConstantFrequency, ConstantFrequency::tRef>("ConstantFrequency",
		init<>())
		.def(init<tScalar>())
		.add_property("frequency", &ConstantFrequency::getFrequency, &ConstantFrequency::setFrequency)
	;
	implicitly_convertible<ConstantFrequency::tRef, ISequencer::tRef>();
};

void WtfAudio::ExportScripting() {
	initWtfAudio();
};
